/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

/**
 * Lehetővé teszi a felhasználói utasítások egységes kezelését függetlenül attól,
 * hogy az adott parancs a standard input-ról vagy egy fájlból érkezett.
 * @author Kéki
 */
public class CommandInterpreter {

    private BufferedReader inputStream;
    private boolean isFileInput;             //Azért van, hogy kiiratásnál tudjuk, hogy az adott parancsot file-ból(==true) vagy konzolról(==false) ovastuk,
    private String fullLine;                        //mert ha fileból, kiírjuk a konzolra.
    private StringTokenizer commandString;
    private String command;
    private String[] parameters;
    private PrintWriter logfile;

    /**
     * Konstruktor (Nincsenek előre megírt utasatások)
     * @param logfile A Controler naplófájljának referenciája
     */
    public CommandInterpreter(PrintWriter logfile) {
        inputStream = new BufferedReader(new InputStreamReader(System.in));
        this.logfile = logfile;
        parameters = new String[2];
        isFileInput = false;
    }

    /**
     * Konstruktor (Van előre megírt utasítássorozat)
     * @param logfile A Controler naplófájljának referenciája.
     * @param file Az előre megírt utasításokat tartlmazó file.
     * @throws FileNotFoundException Amennyiben a megadott bemeneti file nem létezik.
     */
    public CommandInterpreter(PrintWriter logfile, String file) throws FileNotFoundException {
        inputStream = new BufferedReader(new FileReader(file));
        this.logfile = logfile;
        parameters = new String[2];
        isFileInput = true;
    }

    /**
     * Egy új parancs beolvasása.
     * @throws IOException Beolvasási hiba esetén.
     */
    public void ReadCommand() throws IOException {                  //A readLine dobja az IOExceptiont. Én is ilyet dobok később.
        System.out.print("> ");
        fullLine = inputStream.readLine();
        if (fullLine == null) {                                     //Akkor lesz a fullLine null, ha file-ból olvastuk a parancsokat és véget ért a file.
            inputStream = new BufferedReader(new InputStreamReader(System.in)); //Átállunk a billentyűzetre.
            fullLine = "ATTENTION: EOF reached in command source file.";
            isFileInput = false;
            LogCommand();
            fullLine = inputStream.readLine();
        }
        LogCommand();
        commandString = new StringTokenizer(fullLine);
        if (commandString.countTokens() > 3) {
            throw new IOException("Too many words in a command");  //Maximum 3 szó hosszú lehet egy utasítás
        }
        if (commandString.hasMoreTokens()) {
            command = commandString.nextToken();                    //Új Stringet hoztam létre, mert különben csak referencia lenne és a következő netTokennél megváltozna az értéke
        } else {
            throw new IOException("There is no command!");
        }
        if (commandString.hasMoreTokens()) {                        //Új Stringet hoztam létre, mert különben csak referencia lenne és a következő netTokennél megváltozna az értéke
            parameters[0] = commandString.nextToken();
        } else {
            parameters[0] = null;                                   //Ha nem állítom null-ra, akkor amikor lefut egy GetStringparameter hívás, akkor az előző alkalommal beolvasott
            parameters[1] = null;                                   //paramétert adná vissza.
            return;
        }
        if (commandString.hasMoreTokens()) {
            parameters[1] = commandString.nextToken();              //Itt már nem kell új String, mert nem lesz több nextToken, amíg ez kell.
        } else {
            parameters[1] = null;                                   //Ugyan az, mint két kommenttel ezelőtt.
            return;
        }
    }

    /**
     * A legutóbb beolvasott sor parancs részének lekérdezésére
     * @return A legutóbb beolvasott sor parancs része.
     */
    public String GetCommand() {
        return command;
    }

    /**
     * A legutóbb beolvasott sor adott paraméterének lekérdezésére.
     * @param i Kért pareméter sorszáma
     * @return Kért paraméter String formátumban
     * @throws IndexOutOfBoundsException A parameters tömb túlcímzése esetén.
     */
    public String GetStringParameter(int i) throws IndexOutOfBoundsException {
        if (i > 1 || i < 0) {
            throw new IndexOutOfBoundsException("Not supported index of parameters");
        }
        return parameters[i];
    }

    /**
     * A legutóbb beolvasott sor adott paraméterének lekérdezésére.
     * @param i Kért pareméter sorszáma
     * @return Kért paraméter Integer formátumban
     * @throws NumberFormatException Nem megfelelő számformátum esetén.
     * @throws IndexOutOfBoundsException A parameters tömb túlcímzése esetén.
     */
    public int GetIntParameter(int i) throws NumberFormatException, IndexOutOfBoundsException {  //Furcsa módon ezeket a hibadobásokat nem jelezte a NetBeans, hogy ki kell tenni.
        if (i > 1 || i < 0) {
            throw new IndexOutOfBoundsException("Not supported index of parameters");
        }
        return Integer.parseInt(parameters[i]);
    }

    /**
     * Visszaadja a parancs paramétereinek számát.
     * @return A parméterek száma.
     */
    public int GetNumberOfParameters()
    {
        if (parameters[0] == null) return 0;
        if (parameters[1] == null) return 1;
        return 2;
    }

    /**
     * Kiírja a beolvasott parancsot a logfile-ba, amennyiben az létezik.
     */
    private void LogCommand() {         //Már egy kicsit több értelme volt egyenlőre azt a függvényt külön létrehozni.
        if (logfile != null) logfile.println(fullLine);
        if (isFileInput) System.out.println(fullLine);
    }
}
